package com.xiaoq.matrix.weixin.endpoint;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import com.xiaoq.coms.util.JsonUtil;
import com.xiaoq.coms.util.MapUtil;
import com.xiaoq.coms.util.WeixinXmlUtil;
import com.xiaoq.matrix.weixin.Article;
import com.xiaoq.matrix.weixin.WXArticleMessage;
import com.xiaoq.matrix.weixin.WXMassMsgResponse;
import com.xiaoq.matrix.weixin.WXMessage;
import com.xiaoq.matrix.weixin.WXToken;

@RestController
@RequestMapping("/api/v1/weixin")
public class WXEndpoint {
	private static final Logger LOG = LoggerFactory.getLogger(WXEndpoint.class);

	private static final String URL_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
	private static final String URL_MASS_MSG = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token={0}";
	private static final String URL_MASS_MSG_PREVIEW = "https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token={0}";

	@GetMapping(value = "/")
	public void doGet(HttpServletRequest request, HttpServletResponse resp) {

		printRequestContent(request);

		Map<String, String[]> reqMap = request.getParameterMap();
		LOG.info("Get Request: " + JsonUtil.asString(reqMap));
		PrintWriter w = null;
		try {
			w = resp.getWriter();
			String[] echostr = reqMap.get("echostr");
			if (echostr != null && echostr.length > 0) {
				w.print(echostr[0]);
			}
			w.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(w);
		}

	}

	@PostMapping(value = "/")
	public void doPost(HttpServletRequest request, HttpServletResponse resp) {
		try {
			request.setCharacterEncoding("UTF-8");
			resp.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		WXMessage wxMsg = printRequestContent(request);

		Map<String, String[]> reqMap = request.getParameterMap();
		LOG.info("Post Request: " + JsonUtil.asString(reqMap));

		PrintWriter w = null;
		try {
			w = resp.getWriter();
			if (wxMsg != null && wxMsg.getContent() != null) {
				String respStr = null;
				String key = wxMsg.getContent();
				switch (key) {
				case "图文":
					respStr = articleResponse(wxMsg);
					break;
				default:
					respStr = echoResponse(wxMsg);
					break;
				}

				LOG.info(respStr);
				w.print(respStr);
			} else {
				w.append("success");
			}
			w.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(w);
		}
	}

	private String echoResponse(WXMessage wxMsg) {
		WXMessage respMsg = new WXMessage();
		respMsg.setFromUserName(wxMsg.getToUserName());
		respMsg.setToUserName(wxMsg.getFromUserName());
		respMsg.setMsgType("text");
		respMsg.setContent(wxMsg.getContent());
		respMsg.setCreateTime(System.currentTimeMillis() / 1000);
		return WeixinXmlUtil.asXml(respMsg);
	}

	/*
	 * <xml> <ToUserName><![CDATA[toUser]]></ToUserName>
	 * <FromUserName><![CDATA[fromUser]]></FromUserName>
	 * <CreateTime>12345678</CreateTime> <MsgType><![CDATA[news]]></MsgType>
	 * <ArticleCount>2</ArticleCount> <Articles> <item>
	 * <Title><![CDATA[title1]]></Title>
	 * <Description><![CDATA[description1]]></Description>
	 * <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item> <item>
	 * <Title><![CDATA[title]]></Title>
	 * <Description><![CDATA[description]]></Description>
	 * <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item>
	 * </Articles> </xml>
	 * 
	 */
	// 回复图文消息
	private String articleResponse(WXMessage wxMsg) {
		WXArticleMessage respMsg = new WXArticleMessage();
		respMsg.setArticleCount(1);
		respMsg.setMsgType("news");
		respMsg.setCreateTime(System.currentTimeMillis() / 1000);
		respMsg.setFromUserName(wxMsg.getToUserName());
		respMsg.setToUserName(wxMsg.getFromUserName());
		List<Article> articles = new ArrayList<Article>();
		Article article = new Article();
		article.setDescription("图文信息描述");
		article.setPicUrl("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png");
		article.setUrl(
				"https://mp.weixin.qq.com/s?__biz=MzIzMzUyNTU1Mw==&tempkey=OTI1X0ltUXpCZGM4MWt5amZMUFg5SEEyOWhYRzh2UFFaT0J5UE41WGVjVmhyTzJVWllEZnlMNGxoem9qUzVDZmd2NzRBV0lUakVxamxDMzF0NUc3azBsZHZfTDN2Vm9ZVDhBeVRLQldWblkxRjlqWFMtcWtsQWxabjJSZHdEQWdSYUZVUGgwcmxsaGJXcktRdkZnSGU3UWswbng0eE5FX0RmTW5BMjZNWVF%2Bfg%3D%3D&chksm=6885195a5ff2904cc6c048ad375f012ab73f8e1f8a75b77b22a72e87379795f9bfe36fc45e48#rd");
		articles.add(article);
		respMsg.setArticles(articles);
		return WeixinXmlUtil.asXml(respMsg);
	}

	private WXMessage printRequestContent(HttpServletRequest request) {
		try {
			InputStream ins = request.getInputStream();
			WXMessage wxMsg = WeixinXmlUtil.fromInputStream(WXMessage.class, ins);
			if (wxMsg != null) {
				LOG.info(WeixinXmlUtil.asXml(wxMsg));
			}
			return wxMsg;
		} catch (IOException e) {
			LOG.error("读取请求数据失败", e);
		}
		return null;
	}

	@ApiOperation(value = "获取token", notes = "获取token")
	@ApiResponses({ @ApiResponse(code = 200, response = WXToken.class, message = "token") })
	@GetMapping(value = "/token", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public String getToken(
			@RequestParam(value = "appid", required = true) @ApiParam(value = "APPID", required = true) String appid,
			@RequestParam(value = "secret", required = true) @ApiParam(value = "SECRET", required = true) String secret) {

		RestTemplate rest = new RestTemplate();
		String token = rest.getForObject(MessageFormat.format(URL_ACCESS_TOKEN, appid, secret), String.class);
		return token;
	}

	@ApiOperation(value = "群发文本消息", notes = "群发文本消息")
	@ApiResponses({ @ApiResponse(code = 200, response = WXMassMsgResponse.class, message = "发送结果") })
	@PostMapping(value = "/message/mass/sendall/text", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public String massMsgText(
			@RequestParam(value = "userId", required = true) @ApiParam(value = "用户ID", required = true) String userId,
			@RequestParam(value = "msg", required = true) @ApiParam(value = "消息内容", required = true) String msg,
			@RequestParam(value = "accessToken", required = false) @ApiParam(value = "访问令牌", required = true) String accessToken) {

		RestTemplate rest = new RestTemplate();

		Map<String, String> text = MapUtil.buildMapKVGen(new String[][] { { "content", msg } }, String.class,
				String.class);

		Map<String, Object> filter = MapUtil.buildMapKVGen(new Object[][] { { "is_to_all", true } }, String.class,
				Object.class);

		Map<String, Object> body = MapUtil.buildMapKVGen(
				new Object[][] { { "filter", filter }, { "text", text }, { "msgtype", "text" } }, String.class,
				Object.class);

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
		headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
		HttpEntity<String> reqEntity = new HttpEntity<String>(JsonUtil.asString(body), headers);
		LOG.info(JsonUtil.asString(body));
		String respStr = rest.postForObject(MessageFormat.format(URL_MASS_MSG, accessToken), reqEntity,
				String.class);
		return respStr;
	}

	@ApiOperation(value = "群发图文消息", notes = "群发图文消息")
	@ApiResponses({ @ApiResponse(code = 200, response = WXMassMsgResponse.class, message = "发送结果") })
	@PostMapping(value = "/message/mass/sendall/article", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public WXMassMsgResponse massMsgArticle(
			@RequestParam(value = "userId", required = true) @ApiParam(value = "用户ID", required = true) String userId,
			@RequestParam(value = "accessToken", required = false) @ApiParam(value = "访问令牌", required = true) String accessToken,
			@RequestParam(value = "mediaId", required = false) @ApiParam(value = "图文素材ID", required = false) String mediaId) {

		RestTemplate rest = new RestTemplate();

		Map<String, String> news = MapUtil.buildMapKVGen(new String[][] { { "media_id", mediaId } }, String.class,
				String.class);

		Map<String, Object> filter = MapUtil.buildMapKVGen(new Object[][] { { "is_to_all", true } }, String.class,
				Object.class);

		Map<String, Object> body = MapUtil.buildMapKVGen(
				new Object[][] { { "filter", filter }, { "mpnews", news }, { "msgtype", "mpnews" } }, String.class,
				Object.class);

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
		headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
		HttpEntity<String> reqEntity = new HttpEntity<String>(JsonUtil.asString(body), headers);
		LOG.info(JsonUtil.asString(body));
		WXMassMsgResponse resp = rest.postForObject(MessageFormat.format(URL_MASS_MSG, accessToken), reqEntity,
				WXMassMsgResponse.class);
		return resp;
	}

	/*
	 * { "touser":"OPENID", "mpnews":{ "media_id":"123dsdajkasd231jhksad" },
	 * "msgtype":"mpnews" }
	 */
	@ApiOperation(value = "预览图文消息", notes = "预览图文消息")
	@ApiResponses({ @ApiResponse(code = 200, response = WXMassMsgResponse.class, message = "预览结果") })
	@PostMapping(value = "/message/mass/preview", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public WXMassMsgResponse previewMsgArticle(
			@RequestParam(value = "userId", required = true) @ApiParam(value = "用户ID", required = true) String userId,
			@RequestParam(value = "accessToken", required = false) @ApiParam(value = "访问令牌", required = true) String accessToken,
			@RequestParam(value = "mediaId", required = true) @ApiParam(value = "图文素材ID", required = true) String mediaId,
			@RequestParam(value = "toUser", required = true) @ApiParam(value = "用户OPENID", required = true) String toUser) {

		RestTemplate rest = new RestTemplate();

		Map<String, String> news = MapUtil.buildMapKVGen(new String[][] { { "media_id", mediaId } }, String.class,
				String.class);

		Map<String, Object> body = MapUtil.buildMapKVGen(
				new Object[][] { { "touser", toUser }, { "mpnews", news }, { "msgtype", "mpnews" } }, String.class,
				Object.class);

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
		headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
		HttpEntity<String> reqEntity = new HttpEntity<String>(JsonUtil.asString(body), headers);
		LOG.info(JsonUtil.asString(body));
		WXMassMsgResponse resp = rest.postForObject(MessageFormat.format(URL_MASS_MSG_PREVIEW, accessToken), reqEntity,
				WXMassMsgResponse.class);
		return resp;
	}

}
